package com.lwl.blue.seven.test7;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.lwl.blue.seven.dao.Contract7Dao;
import com.lwl.blue.seven.dao.ContractItem7Dao;
import com.lwl.blue.seven.entity.Contract7;
import com.lwl.blue.seven.dto.Contract7ListVO;
import com.lwl.blue.seven.dto.Contract7QueryDTO;
import com.lwl.blue.seven.service.impl.Contract7ServiceImpl;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

import static java.util.List.*;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.*;
import static org.mockito.Mockito.when;

/**
 * 合同DAO层测试类
 * 用于测试Contract7Dao中的各个数据访问方法
 */
//@SpringBootTest
//@Transactional
@ExtendWith(MockitoExtension.class)
public class Contract7DaoTest {

//    @Resource
//    private Contract7Dao contract7Dao;
    // 注入被测试的服务类，并将@Mock标记的依赖注入其中
    @InjectMocks
    private Contract7ServiceImpl contract7Service;

    // 模拟Contract7Dao数据访问层
    @Mock
    private Contract7Dao contract7Dao;

    // 模拟ContractItem7Dao数据访问层
    @Mock
    private ContractItem7Dao contractItem7Dao;

    /**
     * 测试插入合同记录方法
     * 验证Contract7Dao.insert方法是否正常工作
     */
    @Test
    public void testInsert() {
        // 创建测试数据
        Contract7 contract = createTestContract();
        contract.setContractId(1L); // 模拟数据库生成的ID

        // 设置模拟行为：当调用contract7Dao.insert方法时返回1（表示插入成功）
        when(contract7Dao.insert(any(Contract7.class))).thenReturn(1);
       //不必要
       //when(contract7Dao.queryById(anyLong())).thenReturn(contract);

        // 执行测试
        int result = contract7Dao.insert(contract);

        // 验证结果
        assertEquals(1, result); // 验证插入操作返回值为1
        assertNotNull(contract.getContractId()); // 验证合同ID不为空
    }

    /**
     * 测试根据ID查询合同记录方法
     * 验证Contract7Dao.queryById方法是否正常工作
     */
    @Test
    public void testQueryById() {
        // 创建测试数据
        Contract7 contract = createTestContract();
        contract.setContractId(1L);

        // 设置模拟行为：当调用contract7Dao.queryById方法时返回指定的合同对象
        when(contract7Dao.queryById(anyLong())).thenReturn(contract);

        // 执行测试
        Contract7 result = contract7Dao.queryById(contract.getContractId());

        // 验证结果
        assertNotNull(result); // 验证返回结果不为空
        assertEquals(contract.getContractNumber(), result.getContractNumber()); // 验证合同编号一致
        assertEquals(contract.getContractName(), result.getContractName()); // 验证合同名称一致
    }

    /**
     * 测试更新合同记录方法
     * 验证Contract7Dao.update方法是否正常工作
     */
    @Test
    public void testUpdate() {
        // 创建测试数据
        Contract7 contract = createTestContract();
        contract.setContractId(1L);
        contract.setContractName("更新后的合同名称");

        // 设置模拟行为
        when(contract7Dao.update(any(Contract7.class))).thenReturn(1); // 更新操作返回1表示成功
        when(contract7Dao.queryById(anyLong())).thenReturn(contract); // 查询操作返回更新后的合同对象

        // 执行测试
        int result = contract7Dao.update(contract);
        assertEquals(1, result); // 验证更新操作返回值为1

        // 验证结果
        Contract7 updated = contract7Dao.queryById(contract.getContractId());
        assertEquals("更新后的合同名称", updated.getContractName()); // 验证合同名称已更新
    }

    /**
     * 测试根据ID删除合同记录方法（物理删除）
     * 验证Contract7Dao.deleteById方法是否正常工作
     */
    @Test
    public void testDeleteById() {
        // 创建测试数据
        Contract7 contract = createTestContract();
        contract.setContractId(1L);

        // 设置模拟行为
        when(contract7Dao.deleteById(anyLong())).thenReturn(1); // 删除操作返回1表示成功
        when(contract7Dao.queryById(anyLong())).thenReturn(null); // 查询被删除的记录应返回null

        // 执行测试
        int result = contract7Dao.deleteById(contract.getContractId());
        assertEquals(1, result); // 验证删除操作返回值为1

        // 验证结果
        Contract7 deleted = contract7Dao.queryById(contract.getContractId());
        assertNull(deleted); // 验证被删除的记录已不存在
    }

    /**
     * 测试根据ID软删除合同记录方法
     * 验证Contract7Dao.softDeleteById方法是否正常工作
     */
    @Test
    public void testSoftDeleteById() {
        Contract7 contract = createTestContract();
        contract.setContractId(1L);
        contract.setIsDeleted(1); // 模拟软删除后的状态（1表示已删除）

        // 设置模拟行为
        when(contract7Dao.softDeleteById(anyLong())).thenReturn(1); // 软删除操作返回1表示成功
        when(contract7Dao.queryById(anyLong())).thenReturn(contract); // 查询操作返回软删除后的合同对象

        int result = contract7Dao.softDeleteById(contract.getContractId());
        assertEquals(1, result); // 验证软删除操作返回值为1

        Contract7 softDeleted = contract7Dao.queryById(contract.getContractId());
        assertNotNull(softDeleted); // 验证记录仍存在
        assertEquals(Integer.valueOf(1), softDeleted.getIsDeleted()); // 验证isDeleted字段已更新为1
    }

    /**
     * 测试查询合同列表方法
     * 验证Contract7Dao.queryContractList方法是否正常工作
     */
    @Test
    public void testQueryContractList() {
        // 创建测试数据
        Contract7 contract1 = createTestContract();
        contract1.setContractId(1L);
        contract1.setContractNumber("HT001");
        contract1.setContractName("测试合同1");

        Contract7 contract2 = createTestContract();
        contract2.setContractId(2L);
        contract2.setContractNumber("HT002");
        contract2.setContractName("测试合同2");

        // 创建模拟的分页结果
        List<Contract7ListVO> records = Arrays.asList(new Contract7ListVO(), new Contract7ListVO());

        Page<Contract7ListVO> mockPage = new Page<>(1, 10);
        mockPage.setRecords(records);
        mockPage.setTotal(2L);

        // 设置模拟行为：当调用queryContractList方法时返回模拟的分页结果
        when(contract7Dao.queryContractList(any(Page.class), any(Contract7QueryDTO.class)))
                .thenReturn(mockPage);

        // 查询测试
        Page<Contract7ListVO> page = new Page<>(1, 10);
        Contract7QueryDTO queryDTO = new Contract7QueryDTO();
        queryDTO.setKeyword("测试");

        Page<Contract7ListVO> result = contract7Dao.queryContractList(page, queryDTO);

        assertNotNull(result); // 验证返回结果不为空
        assertTrue(result.getTotal() >= 2); // 验证总记录数至少为2
        assertNotNull(result.getRecords()); // 验证记录列表不为空
        assertFalse(result.getRecords().isEmpty()); // 验证记录列表不为空
    }

    /**
     * 测试检查合同编号是否存在方法
     * 验证Contract7Dao.checkContractNumberExists方法是否正常工作
     */
    @Test
    public void testCheckContractNumberExists() {
        Contract7 contract = createTestContract();
        contract.setContractId(1L);

        // 设置模拟行为
        when(contract7Dao.checkContractNumberExists(anyString(), any())).thenReturn(1); // 存在时返回1
        when(contract7Dao.checkContractNumberExists(eq("NOT_EXISTS"), any())).thenReturn(0); // 不存在时返回0

        // 检查存在的合同编号
        int exists = contract7Dao.checkContractNumberExists(contract.getContractNumber(), null);
        assertTrue(exists > 0); // 验证存在的合同编号返回值大于0

        // 检查不存在的合同编号
        int notExists = contract7Dao.checkContractNumberExists("NOT_EXISTS", null);
        assertEquals(0, notExists); // 验证不存在的合同编号返回值为0
    }

    /**
     * 测试更新合同状态方法
     * 验证Contract7Dao.updateContractStatus方法是否正常工作
     */
    @Test
    public void testUpdateContractStatus() {
        Contract7 contract = createTestContract();
        contract.setContractId(1L);
        contract.setStatus(30); // 设置为审核通过状态
        contract.setAuditPersonId(1L); // 设置审核人ID

        // 设置模拟行为
        when(contract7Dao.updateContractStatus(anyLong(), anyInt(), any())).thenReturn(1); // 更新状态操作返回1表示成功
        when(contract7Dao.queryById(anyLong())).thenReturn(contract); // 查询操作返回更新后的合同对象

        int result = contract7Dao.updateContractStatus(contract.getContractId(), 30, 1L);
        assertEquals(1, result); // 验证更新状态操作返回值为1

        Contract7 updated = contract7Dao.queryById(contract.getContractId());
        assertEquals(Integer.valueOf(30), updated.getStatus()); // 验证状态已更新为30
        assertEquals(Long.valueOf(1L), updated.getAuditPersonId()); // 验证审核人ID已更新
    }

    /**
     * 测试批量软删除合同记录方法
     * 验证Contract7Dao.batchSoftDelete方法是否正常工作
     */
    @Test
    public void testBatchSoftDelete() {
        Contract7 contract1 = createTestContract();
        contract1.setContractId(1L);
        contract1.setIsDeleted(1); // 设置为已删除状态

        Contract7 contract2 = createTestContract();
        contract2.setContractId(2L);
        contract2.setContractNumber("HT002");
        contract2.setIsDeleted(1); // 设置为已删除状态

        List<Long> idList = Arrays.asList(1L, 2L); // 要删除的合同ID列表

        // 设置模拟行为
        when(contract7Dao.batchSoftDelete(anyList(), anyLong())).thenReturn(2); // 批量删除操作返回2表示成功删除2条记录
        when(contract7Dao.queryById(1L)).thenReturn(contract1); // 查询ID为1的合同返回contract1
        when(contract7Dao.queryById(2L)).thenReturn(contract2); // 查询ID为2的合同返回contract2

        int result = contract7Dao.batchSoftDelete(idList, 1L);
        assertEquals(2, result); // 验证批量删除操作返回值为2

        Contract7 deleted1 = contract7Dao.queryById(1L);
        Contract7 deleted2 = contract7Dao.queryById(2L);
        assertEquals(Integer.valueOf(1), deleted1.getIsDeleted()); // 验证第一条记录的isDeleted字段已更新为1
        assertEquals(Integer.valueOf(1), deleted2.getIsDeleted()); // 验证第二条记录的isDeleted字段已更新为1
    }

    /**
     * 创建测试用的合同对象
     * 用于生成测试数据的辅助方法
     * @return Contract7 测试用合同对象
     */
    private Contract7 createTestContract() {
        Contract7 contract = new Contract7();
        contract.setContractNumber("HT" + System.currentTimeMillis()); // 使用当前时间戳生成唯一合同编号
        contract.setContractName("测试合同"); // 合同名称
        contract.setTransactionType("采购"); // 交易类型
        contract.setSupplierId(1); // 供应商ID
        contract.setStatus(10); // 合同状态（10:草稿）
        contract.setCreateUserId(1L); // 创建人ID
        contract.setCreateTime(new Date()); // 创建时间
        contract.setUpdateUserId(1L); // 更新人ID
        contract.setUpdateTime(new Date()); // 更新时间
        contract.setTotalAmount(new BigDecimal("1000.00")); // 合同总金额
        contract.setVersion(1); // 版本号
        contract.setIsDeleted(0); // 删除标识（0:未删除）
        contract.setRedFlag(0); // 红冲标识（0:未红冲）
        return contract;
    }
}
